<?php defined('BASEPATH') OR exit('No direct script access allowed');
/**
 * Description: 订单修改接口
 *
 * @author      Eden
 * @datetime    2016/12/1 22:56
 * @copyright   Beijing CmsTop Technology Co.,Ltd.
 */
class Edit_Model extends API_Model
{

    // 参数
    private $params;

    private $goods = array();

    private $filterGoods = array();

    private $return = array();

    private $errorData = array();

    // 代金券等额面值
    private $voucherPrice = 0;

    // 商品总重量
    private $goodsWeight = 0;

    /**
     * 初始化
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * 主程序
     * @param array $params
     */
    public function run(Array $params) {
        $params = [
            'userId' => 1,
            'orderId' => 58,
            'addressId' => 2,
            'goods' => '5:2,6:2',
            'payMode' => 'online',
            'voucher' => '',
            'totalPrice' => 209.08,
            'expressPrice' => 192,
            'goodsPrice' => 17.08
        ];
        $this->params = $params;
        $send['state'] = false;
        do {

            if (!$this->_checkParams() || !$this->checkUser()
                || !$this->checkGoods() || !$this->checkAddress()) {
                $send['error'] = $this->getError() ? $this->getError() : '订单修改失败';

                if (!empty($this->errorData)) {
                    $send['data'] = $this->errorData;
                }
                break;
            }

            if (!$this->editOrder()) {
                $send['error'] = $this->getError() ? $this->getError() : '订单修改失败';
                break;
            }

            $send['state'] = true;
            $send['data'] = $this->return;

        } while(false);
        $this->output->send($send);
    }

    /**
     * 编辑
     * @return bool
     */
    private function editOrder()
    {
        try {
            $this->db->trans_start();
            $goodsData = array();
            $totalPrice = 0;
            $totalWeight = 0;
            foreach ($this->goods as $key => $good) {
                $num = intval($this->filterGoods[$key]);
                $goodsData[] = array(
                    'orderId' => $this->params['orderId'],
                    'goodsId' => $key,
                    'num' => $num,
                    'price' => $good['price']
                );
                $totalPrice += $good['price'] * $num;
                $totalWeight += $good['expressWeight'] * $num;
            }

            if (!$this->checkPrice($totalPrice, $totalWeight)) {
                return false;
            }

            $userOrderData = array(
                'addressId' => $this->params['addressId'],
                'payMode' => $this->params['payMode'],
                'totalPrice' => $this->params['totalPrice'],
                'goodsPrice' => $this->params['goodsPrice'],
                'expressPrice' => $this->params['expressPrice'],
                'message' => value($this->params, 'message', ''),
                'voucher' => empty($this->params['voucher']) ? '' : $this->params['voucher'],
            );
            $oDb = clone($this->db);
            $oDb->where('id', $this->params['orderId']);
            $oDb->update('user_order', $userOrderData);

            $uogDelDb = clone($this->db);
            $uogDelDb->where('orderId', $this->params['orderId']);
            $uogDelDb->delete('user_order_goods');

            $uogDb = clone($this->db);
            $uogDb->insert_batch('user_order_goods', $goodsData);

            $this->db->trans_complete();
            if ($this->db->trans_status() === false) {
                $this->setError('下单失败');
                return false;
            }

            $this->return = array_merge(array(
                'orderId' => intval($this->params['orderId']),
            ), $userOrderData);
            return true;
        } catch(PDOException $e) {
            $this->setError('修改失败');
        }
        return false;
    }

    /**
     * 检查前后台的价格
     * @param int $totalGoodsPrice
     * @param int $totalWeight
     * @return bool
     */
    private function checkPrice($totalGoodsPrice = 0, $totalWeight = 0)
    {
        $totalPrice = doubleval($this->params['totalPrice']);
        $goodsPrice = doubleval($this->params['goodsPrice']);
        $expressPrice = doubleval($this->params['expressPrice']);

        // 对比商品金额
        if (bccomp($goodsPrice, $totalGoodsPrice, 2) !== 0) {
            $this->setError('商品金额不符');
            return false;
        }

        $expressCosts = $this->getExpressCosts($totalWeight);
        if (bccomp($expressPrice, $expressCosts, 2) !== 0) {
            $this->setError('运费金额不符');
            return false;
        }

        // 对比用代金券后的金额
        $total = $goodsPrice + $expressCosts;
        if (!empty($this->params['voucher'])) {
            $total += $this->voucherPrice;
            if (bccomp($total, $totalPrice, 2) !== 0) {
                $this->setError('总金额有误');
                return false;
            }
        } else {
            if (bccomp($total, $totalPrice, 2) !== 0) {
                $this->setError('总金额有误');
                return false;
            }
        }
        return true;
    }

    /**
     * 计算运费
     * @param int $totalWeight
     * @return float|int
     */
    private function getExpressCosts($totalWeight = 0)
    {
        $config = $this->_getShippingCosts();
        if ($config['payer'] == 'buyer') {
            $costs = $config['costs'];
            $firstWeight = $costs['firstWeight'];
            $firstCost = $costs['firstCost'];
            $incrWeight = $costs['incrWeight'];
            $incrCost = $costs['incrCost'];
            if ($firstWeight >= $totalWeight) {
                return $firstCost;
            } else {
                $left = $totalWeight - $firstWeight;
                return ceil($left / $incrWeight) * $incrCost + $firstCost;
            }

        } else {
            return 0;
        }
    }

    /**
     * 获取跟客户端一样的物流配置
     * @return array
     */
    private function _getShippingCosts()
    {
        $default = array(
            'payer' => 'seller',
            'costs' => []
        );
        // 前期只考虑到统一的价格的情况,没有进行区域区分
        $db = clone($this->db);
        $q = $db->get_where('express_template', array('using' => 1));
        $row = $q->row_array();
        if (!$row) {
            return $default;
        }

        if ($row['payer'] == 'seller') {
            return $default;
        }

        $payer = $row['payer'];
        if ($row['payType'] == 'weight') {
            $q = $this->db->get_where('express_weight', array('tmpId' => $row['id']));
            $row = $q->row_array();
            if (empty($row)) {
                return $default;
            }
            $default['payer'] = $payer;
            $default['costs'] = array(
                'firstWeight' => doubleval($row['firstWeight']),
                'firstCost' => doubleval($row['firstCost']),
                'incrWeight' => doubleval($row['incrWeight']),
                'incrCost' => doubleval($row['incrCost'])
            );
        }

        return $default;
    }

    /**
     * @return bool
     */
    private function checkAddress()
    {
        try {
            $addDb = clone($this->db);
            $query = $addDb->get_where('user_address', array(
                'id' => $this->params['addressId'],
                'userId' => $this->params['userId']
            ));
            $address = $query->row_array();
            if (empty($address)) {
                $this->setError('用户地址不存在');
                return false;
            }
            return true;
        } catch (PDOException $e) {}
        return false;
    }

    /**
     * 检查商品是否存在
     * @return bool
     */
    private function checkGoods()
    {
        try {
            $goodsDb = clone($this->db);

            $goodsIds = array();
            $filterGoods = array();
            foreach($this->params['goods'] as $good) {
                $goodsIds[] = $good['goodsId'];
                $filterGoods[$good['goodsId']] = $good['num'];
            }
            $this->filterGoods = $filterGoods;

            $goodsDb->where_in('id', $goodsIds);
            $query = $goodsDb->get('base_goods');
            $res = $query->result_array();

            if ($res) foreach ($res as $good) {
                if ($good['status'] != 1) {
                    $this->setError('含有下架商品');
                    $this->errorData = array(
                        'goodsId' => $good['id'],
                        'status' => 'offSale'
                    );
                    return false;
                }

                if ($good['stock'] < $filterGoods[$good['id']]) {
                    $this->errorData = array(
                        'goodsId' => $good['id'],
                        'stock' => intval($good['stock'])
                    );
                    $this->setError('商品库存不足');
                    return false;
                }
                $goodsId = $good['id'];
                $this->goods[$goodsId] = $good;
                $this->goodsWeight += doubleval($good['expressWeight']);
            } else {
                $this->setError('该商品不存在');
                return false;
            }

            return true;
        } catch (PDOException $e) {
            $this->setError('商品查询失败');
        }
        return false;
    }

    /**
     * 用户登录状态
     * @return bool
     */
    private function checkUser()
    {
        $userId = value($this->params, 'userId');
        $userDb = clone($this->db);

        $query = $userDb->get_where('user', array('id' => $userId));
        $row = $query->row_array();

        if (empty($row)) {
            $this->setError('用户不存在');
            return false;
        }

        if ($row['status'] != 1) {
            $this->setError('用户受限');
            return false;
        }

        return true;
    }

    /**
     * 检查参数
     * @return bool
     */
    private function _checkParams()
    {

        if ($this->input->method(true) !== 'POST') {
            //$this->setError('非法请求');
            //return false;
        }

        $needs = array('userId', 'orderId', 'goods', 'addressId', 'totalPrice', 'goodsPrice', 'payMode');
        $validGoods = array();
        foreach ($needs as $field) {
            if (!array_key_exists($field, $this->params) || empty($this->params[$field])) {
                $this->setError('参数错误');
                return false;
            }
        }

        if (!in_array($this->params['payMode'], array('online', 'delivery'))) {
            $this->setError('不支持的支付方式');
            return false;
        }

        try {
            $goods = explode(',', $this->params['goods']);
            if (empty($goods)) {
                $this->setError('参数错误');
                return false;
            }

            if (is_array($goods)) foreach($goods as $good) {
                $g = explode(':', $good);
                $goodsId = $g[0];
                $num = $g[1];
                $validGoods[] = [
                    'goodsId' => $goodsId,
                    'num' => $num
                ];
            } else {
                $this->setError('参数错误');
                return false;
            }

        } catch(Exception $e) {
            $this->setError('参数错误');
            return false;
        }

        if (empty($validGoods)) {
            $this->setError('请选择商品');
            return false;
        }

        if (!isset($this->params['expressPrice'])) {
            $this->params['expressPrice'] = 0;
        }

        if (!isset($this->params['message'])) {
            $this->params['message'] = '';
        }

        // 代金券
        if (!empty($this->params['voucher']) && !$this->checkVoucher($this->params['userId'], $this->params['voucher'])) {
            return false;
        }

        // 订单状态
        if (!$this->checkOrderStatus()) {
            return false;
        }

        $this->params['goods'] = $validGoods;
        return true;
    }

    /**
     * 检查订单状态
     * @return bool
     */
    private function checkOrderStatus()
    {
        $db = clone($this->db);
        $q = $db->get_where('user_order', array('id' => $this->params['orderId']));
        $row = $q->row_array();
        if (empty($row)) {
            $this->setError('订单不存在');
            return false;
        }

        if ($row['status'] != 'Unpaid') {
            $this->setError('当前订单状态无法修改');
            return false;
        }
        return true;
    }

    /**
     * 代金券
     * @param $userId
     * @param string $voucher
     * @return bool
     */
    private function checkVoucher($userId, $voucher = '')
    {
        $db = clone($this->db);
        $q = $db->get_where('user_voucher', array('userId' => $userId, 'status' => 1, 'voucher' => $voucher));
        $row = $q->row_array();
        if (empty($row)) {
            $this->setError('无效的代金券');
            return false;
        }

        $expires = strtotime($row['expires']);
        if ($expires < time()) {
            $this->setError('代金券已过期');
            return false;
        }

        if ($row['used'] != 1) {
            $this->setError('代金券已被使用');
            return false;
        }

        $this->voucherPrice = doubleval($row['price']);

        return true;
    }
}